if (nv.CreateNamespace("nv.http")) {
    nv.http.requestCount = 1;
    nv.http.DataTypes = {
        JSON: 'json',
        TEXT: 'text'
    };
    nv.http.Method = {
        GET: 'GET',
        POST: 'POST'
    };
    nv.http.Base = function (url, method) {
        var $this = this;
        $this.RequestID = nv.http.requestCount++;
        $this.RequestUrl = url;
        $this.Method = method;
        $this.Timeout = 7000;
        $this.OnSuccess = new nv.Event();
        $this.OnFailure = new nv.Event();
        $this.OnAbort = new nv.Event(true);
        $this.DataType = nv.http.DataTypes.JSON;
        $this.lastSendParamsForDebuggingOnly = null;
        $this.Send = function (params) {
            $this.lastSendParamsForDebuggingOnly = params;
            params._xhr = 1;
            return $this._Send(params);
        };
        $this._Send = nv.util.OOP['abstract']('nv.http.Base.Send');
        $this.Abort = function () {
            $this.OnSuccess.Reset();
            $this.OnFailure.Reset();
            $this.OnAbort.Trigger();
        };
        $this.TriggerSuccess = function (data) {
            switch ($this.DataType) {
                case nv.http.DataTypes.JSON:
                    try {
                        data = "(" + data + ")";
                        data = data.replace(/\n/g, "\\\n");
                        data = eval(data);
                    } catch (e) {
                        nv.error("Invalid JSON data received by http.js from URL: " + $this.RequestUrl + " and data: " + nv.Json.stringify($this.lastSendParamsForDebuggingOnly));
                        nv.error(data);
                        $this.TriggerFailure("invalid data");
                        return;
                    }
                    break;
                case nv.http.DataTypes.TEXT:
                    break;
                default:
                    break;
            }
            $this.OnSuccess.Trigger(data);
        };
        $this.TriggerFailure = function (reason) {
            $this.OnFailure.Trigger(reason);
        };
        $this.GetQueryString = function (params) {
            return nv.util.Url.getQueryString(params);
        };
        $this.WrapCallbackAsGlobal = function (callback) {
            var uniqueCallbackName = "Wikinvest_HTTP_Callback_" + $this.RequestID;
            window[uniqueCallbackName] = function (data) {
                callback(data);
            };
            return uniqueCallbackName;
        };
    };
    nv.http.GetTimestampForCachedRequest = function (cacheLifeInSeconds) {
        var timestamp = (new Date()).getTime();
        timestamp = Math.floor(timestamp / (cacheLifeInSeconds * 1000)) * (cacheLifeInSeconds * 1000);
        return timestamp;
    };
    nv.http.Factory = function (url, method) {
        if (/^\/\//.test(url)) {
            url = document.location.protocol + url;
        }
        method = method.toUpperCase();
        if (nv.http.Serverside) {
            return new nv.http.Serverside(url, method);
        }
        if (!url.match(/^http(s)?:\/\//i)) {
            return new nv.http.Ajax(url, method);
        } else {
            var url1 = nv.util.Url.parseUrl(url);
            var url2 = nv.util.Url.parseUrl(document.location.href);
            var compareUrlProperty = function (property) {
                if (typeof url1[property] === "undefined") {
                    return typeof url2[property] === "undefined";
                } else if (typeof url2[property] === "undefined") {
                    return false;
                } else {
                    return url1[property] === url2[property];
                }
            };
            if (compareUrlProperty('scheme') && compareUrlProperty('host') && compareUrlProperty('port')) {
                return new nv.http.Ajax(url, method);
            } else {
                if (method == nv.http.Method.GET) {
                    return new nv.http.ScriptNode(url);
                } else {
                    return new nv.http.Flash(url, method);
                }
            }
        }
    };
    nv.http.request = function (params) {
        if (!params.url) {
            nv.error("[nv.http.request] 'url' property not specified");
            return;
        }
        var method = nv.http.Method.GET;
        if (params.method) {
            method = params.method;
        }
        var request = nv.http.Factory(params.url, method);
        if (params.timeout) {
            request.Timeout = params.timeout;
        }
        if (params.dataType) {
            request.DataType = params.dataType;
        }
        if (params.success) {
            request.OnSuccess.bindOnce(params.success);
        }
        if (params.error) {
            request.OnFailure.bindOnce(params.error);
        }
        var data = {};
        if (params.data) {
            data = params.data;
        }
        request.Send(data);
    };
    nv.http.Beacon = function (params) {
        if (!params.url) {
            nv.error("[nv.http.Beacon] 'url' property not specified");
            return;
        }
        var data = {};
        if (params.data) {
            data = params.data;
        }
        if (typeof data.timestamp == "undefined") {
            data.timestamp = new Date().getTime().toString() + Math.random().toString().replace(/^0./, "");
        }
        var querystring = nv.util.URL.GetQueryString(data);
        var img = new Image();
        img.src = params.url + "?" + querystring;
    };
}